#include "loopbuf.h"

BOOL initMsgQ(ifly_msgQ_t *mq, u32 unitNum, u32 unitLen)
{
	int i;
	
	if (mq && unitNum && unitLen)
	{
		mq->rpos    = 0;
		mq->wpos    = 0;
		mq->unitNum = unitNum;
		mq->unitLen = unitLen;
		mq->buf = (u8 *)malloc(unitNum * (sizeof(u32) + unitLen));
		if (mq->buf == NULL)
		{
			printf("initMsgQ:malloc failed\n");
			return FALSE;
		}
		pthread_mutex_init(&mq->lock, NULL);
		sem_init(&mq->rsem, 0, unitNum);
		sem_init(&mq->wsem, 0, unitNum);
		for (i = 0; i < unitNum; i++)
		{
			sem_wait(&mq->rsem);
		}
		return TRUE;
	}
	printf("initMsgQ:param error\n");
	return FALSE;
}

int readMsgQ(ifly_msgQ_t *mq, u8 *pBuf, u32 readLen)
{
	int realLen;
	if (mq && pBuf && readLen)
	{
		sem_wait(&mq->rsem);
		
		//pthread_mutex_lock(&mq->lock);
		
		memcpy(&realLen, mq->buf + mq->rpos * (sizeof(u32) + mq->unitLen), sizeof(u32));
		realLen = min(realLen, readLen);
		memcpy(pBuf, mq->buf + mq->rpos * (sizeof(u32) + mq->unitLen) + sizeof(u32), realLen);
		
		mq->rpos = (mq->rpos + 1) % mq->unitNum;
		
		//pthread_mutex_unlock(&mq->lock);
		
		sem_post(&mq->wsem);
		
		return realLen;
	}
	printf("readMsgQ:param error\n");
	return -1;
}

int writeMsgQ(ifly_msgQ_t *mq,u8 *pBuf,u32 writeLen)
{
	if (mq && pBuf && writeLen <= mq->unitLen)
	{
		sem_wait(&mq->wsem);
		
		pthread_mutex_lock(&mq->lock);
		
		memcpy(mq->buf + mq->wpos * (sizeof(u32) + mq->unitLen), &writeLen, sizeof(u32));
		memcpy(mq->buf + mq->wpos * (sizeof(u32) + mq->unitLen) + sizeof(u32), pBuf, writeLen);
		
		mq->wpos = (mq->wpos + 1) % mq->unitNum;
		
		sem_post(&mq->rsem);
		
		pthread_mutex_unlock(&mq->lock);
		
		return writeLen;
	}
	printf("writeMsgQ:param error,mq=%x,pBuf=%x,writeLen=%d,mq->unitLen=%d\n",(int)mq,(int)pBuf,writeLen,mq->unitLen);
	return -1;
}

BOOL destroyMsgQ(ifly_msgQ_t *mq)
{
	if (mq)
	{
		pthread_mutex_destroy(&mq->lock);
		sem_destroy(&mq->rsem);
		sem_destroy(&mq->wsem);	
		if (mq->buf != NULL)
		{
			free(mq->buf);
			mq->buf = NULL;
		}
		return TRUE;
	}
	printf("destroyMsgQ:param error\n");
	return FALSE;
}

BOOL GetMsgQReadInfo(ifly_msgQ_t *mq,u8 **ppBuf,u32 *pReadLen)
{
	if (mq && ppBuf && pReadLen)
	{
		sem_wait(&mq->rsem);
		
		//pthread_mutex_lock(&mq->lock);
		
		memcpy(pReadLen, mq->buf + mq->rpos * (sizeof(u32) + mq->unitLen), sizeof(u32));
		*ppBuf = mq->buf + mq->rpos * (sizeof(u32) + mq->unitLen) + sizeof(u32);
		
		return TRUE;
	}
	printf("GetMsgQReadInfo:param error\n");
	return FALSE;
}

BOOL GetMsgQReadInfo2(ifly_msgQ_t *mq,u8 **ppBuf,u32 *pReadLen)
{
	if (mq && ppBuf && pReadLen)
	{
		if (-1 == sem_trywait(&mq->rsem))
		{
			 return FALSE;
		}

		//pthread_mutex_lock(&mq->lock);
		
		memcpy(pReadLen, mq->buf + mq->rpos * (sizeof(u32) + mq->unitLen), sizeof(u32));
		*ppBuf = mq->buf + mq->rpos * (sizeof(u32) + mq->unitLen) + sizeof(u32);
		
		return TRUE;
	}
	printf("GetMsgQReadInfo:param error\n");
	return FALSE;
}

BOOL skipReadMsgQ(ifly_msgQ_t *mq)
{
	if (mq)
	{
		mq->rpos = (mq->rpos + 1) % mq->unitNum;
		//pthread_mutex_unlock(&mq->lock);
		sem_post(&mq->wsem);
		return TRUE;
	}
	printf("skipReadMsgQ:param error\n");
	return FALSE;
}

BOOL GetMsgQWriteInfo(ifly_msgQ_t *mq,u8 **ppBuf,u32 *pWriteLen)
{
	if (mq && ppBuf && pWriteLen)
	{
		#if 0
		sem_wait(&mq->wsem);
		#else
		if (-1 == sem_trywait(&mq->wsem))//wrchen 090307
		{
			return FALSE;
		}
		#endif
		
		pthread_mutex_lock(&mq->lock);
		
		int tmpWPos = mq->wpos;
		mq->wpos = (mq->wpos + 1) % mq->unitNum;
		
		//pthread_mutex_unlock(&mq->lock);
		
		memcpy(mq->buf + tmpWPos * (sizeof(u32) + mq->unitLen), pWriteLen, sizeof(u32));
		*ppBuf = mq->buf + tmpWPos * (sizeof(u32) + mq->unitLen) + sizeof(u32);
		
		return TRUE;
	}
	printf("GetMsgQWriteInfo:param error\n");
	return FALSE;
}

BOOL skipWriteMsgQ(ifly_msgQ_t *mq)
{
	if (mq)
	{
		sem_post(&mq->rsem);
		
		pthread_mutex_unlock(&mq->lock);
		
		return TRUE;
	}
	printf("skipWriteMsgQ:param error\n");
	return FALSE;
}

u32 getReadPosMsgQ(ifly_msgQ_t *mq)
{
	int pos=0;
	int possem=0;

	if(mq)
	{
		possem = sem_getvalue(&mq->rsem,&pos);

		return pos;
	}
	printf("skipWriteMsgQ:param error\n");
	return -1;
}

